package com.atguigu.gmall.payment.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.model.enums.PaymentType;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.payment.config.AlipayConfig;
import com.atguigu.gmall.payment.service.AlipayService;
import com.atguigu.gmall.payment.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Map;

/**
 * @author atguigu-mqx
 */
//  @RestController  // @ResponseBody + @Controller
@Controller
@RequestMapping("/api/payment/alipay")
@RefreshScope
public class AlipayController {

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private PaymentService paymentService;

    @Value("${app_id}")
    private String app_id;

    //  接收数据
    private String localNotifyId;
    //  //	@{http://api.gmall.com/api/payment/alipay/submit/{orderId}(orderId=${orderInfo.id})}
    @GetMapping("/submit/{orderId}")
    @ResponseBody
    public String submitOrder(@PathVariable Long orderId){
        //  声明变量
        String from = null;
        try {
            from = alipayService.createaliPay(orderId);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //  返回数据
        return from;
    }

    //  设置同步回调地址：
    //  http://api.gmall.com/api/payment/alipay/callback/return
    @GetMapping("callback/return")
    public String callbackReturn(){
        //  处理订单结果： 改变订单状态！
        //  重定向到支付成功页面！ http://payment.gmall.com/pay/success.html
        return "redirect:"+ AlipayConfig.return_order_url;
    }

    //  设置异步回调： 必须通过内网穿透 将 支付宝服务器上的信息 远程传递给当前的服务器！
    //  http://n8sa9h.natappfree.cc/api/payment/alipay/callback/notify
    //  http://a4bgbw.natappfree.cc/api/payment/alipay/callback/notify
    //  https://商家网站通知地址?voucher_detail_list=[{"amount":"0.20","merchantContribute":"0.00","name":"5折券","otherContribute":"0.20","type":"ALIPAY_DISCOUNT_VOUCHER","voucherId":"2016101200073002586200003BQ4"}]&fund_bill_list=[{"amount":"0.80","fundChannel":"ALIPAYACCOUNT"},{"amount":"0.20","fundChannel":"MDISCOUNT"}]&subject=PC网站支付交易&trade_no=2016101221001004580200203978&gmt_create=2016-10-12 21:36:12&notify_type=trade_status_sync&total_amount=1.00&out_trade_no=mobile_rdm862016-10-12213600&invoice_amount=0.80&seller_id=2088201909970555&notify_time=2016-10-12 21:41:23&trade_status=TRADE_SUCCESS&gmt_payment=2016-10-12 21:37:19&receipt_amount=0.80&passback_params=passback_params123&buyer_id=2088102114562585&app_id=2016092101248425&notify_id=7676a2e1e4e737cff30015c4b7b55e3kh6& sign_type=RSA2&buyer_pay_amount=0.80&sign=***&point_amount=0.00
    @PostMapping("callback/notify")
    @ResponseBody
    public String callbackNofity(@RequestParam Map<String, String> paramMap){
        //  异步通知针对当前的订单 会产生一个 notify_id ； 这个是唯一的， 只有返回success 时，这个id 才会失效！
        //  Map<String, String> paramsMap = ... //将异步通知中收到的所有参数都存放到map中
        boolean signVerified = false; //调用SDK验证签名
        try {
            signVerified = AlipaySignature.rsaCheckV1(paramMap, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //  获取商户订单号
        String outTradeNo = paramMap.get("out_trade_no");
        String totalAmount = paramMap.get("total_amount");
        String appId = paramMap.get("app_id");
        String tradeStatus = paramMap.get("trade_status");
        //  过滤重复：获取 notify_id 判断是否是同一条数据！
        String notifyId = paramMap.get("notify_id");
        //  先赋值：
        //  this.localNotifyId = notifyId;
        //        if (notifyId.equals(localNotifyId)){
        //            //  同一条数据 ：同一条数据发送了多个请求过来，这些请求：第一次就是success 则直接跳过！ 如果不是success,则处理！并返回！
        //        }else {
        //            // 不是同一条数据处理并赋值：
        //            this.localNotifyId = notifyId; count++; 获取到返回结果！ 如果是success 直接返回了！
        //        }
        if(signVerified){
            // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
            // out_trade_no total_amount seller_id app_id；
            //  查询就可以了。
            PaymentInfo paymentInfoQuery = this.paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
            BigDecimal totalAmount2 = new BigDecimal(totalAmount);
            // BigDecimal totalAmount1 = paymentInfoQuery.getTotalAmount();
            BigDecimal totalAmount1 = new BigDecimal("0.01");
            if (paymentInfoQuery==null || totalAmount2.compareTo(totalAmount1)!=0 || !appId.equals(app_id)){
                return "failure";
            }

            //  判断交易状态！ 只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功!
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                //  更改交易记录的状态！
                this.paymentService.paySuccess(outTradeNo,PaymentType.ALIPAY.name(),paramMap);
                //  支付成功！
                return "success";
            }
        }else{
            // TODO 验签失败则记录异常日志，并在response中返回failure.
        }
        return "success";
    }


    //  编写退款接口：
    // 发起退款！http://localhost:8205/api/payment/alipay/refund/20
    @RequestMapping("refund/{orderId}")
    @ResponseBody
    public Result refund(@PathVariable Long orderId){
        //  退款
        Boolean flag =  alipayService.refund(orderId);

        return Result.ok(flag);

    }

    //  关闭支付宝交易接口：
    //  http://localhost:8205/api/payment/alipay/closePay/25
    // 根据订单Id关闭订单
    @GetMapping("closePay/{orderId}")
    @ResponseBody
    public Boolean closePay(@PathVariable Long orderId){
        //  调用方法
        Boolean flag =  alipayService.closePay(orderId);

        return flag;
    }

    //  http://localhost:8205/api/payment/alipay/checkPayment/30
    // 查看是否有交易记录
    @RequestMapping("checkPayment/{orderId}")
    @ResponseBody
    public Boolean checkPayment(@PathVariable Long orderId){
        //  调用方法
        Boolean flag =  alipayService.checkPayment(orderId);

        return flag;
    }

    //  查询paymentInfo 记录
    @GetMapping("getPaymentInfo/{outTradeNo}")
    @ResponseBody
    public PaymentInfo getPaymentInfo(@PathVariable String outTradeNo){
        //  返回记录
        return paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
    }

}
